package com.qf.juc.day02;

import sun.misc.Unsafe;

import java.lang.reflect.Field;

/**
 *
 * 比较并交换    乐观锁的底层实现过程
 *
 * CAS :
 * @author lixu
 */
public class CasDemo {


    //变量
    private int number;// Mysql: version


    public static void main(String[] args) {
        //Unsafe: 不安全的类 ： 直接控制 电脑的内存条  直接向电脑申请内存空间
        //Unsafe unsafe = new Unsafe();
        //Unsafe unsafe = Unsafe.getUnsafe();//应用类加载器
        //java.lang.SecurityException: Unsafe : 报错： 安全异常

        //VM.isSystemDomainLoader(var0.getClassLoader()) :
        // 判断当前调用者是谁？   JVM：只允许引导类加载器进行加载    JVM：自己是可以的
        // JVM :
        // 三大类加载器
        //   1、引导类加载器  祖父
        //   2、扩展类加载器  父
        //   3、应用类加载器  子   同学们写的代码
        //   4、自定义类加载器


        CasDemo casDemo = new CasDemo();
        //1、判断原始值是否是0
        //1.1 与原始值相同  允许修改  改成100
        //1.2 与原始值不同  不允许修改  不能改成100
        System.out.println("修改是否成功:" + casDemo.compareAndSwap(10, 100));


    }

    /**
     * CAS
     *    比较并交换                 Mysql： 乐观锁
     *     1、变量  number          1、变量 version
     *     2、原始  0               2、原始  1
     *     3、修改后  10            3、修改  2
     *
     * @param oldValue
     * @param newValue
     */
    public boolean compareAndSwap(int oldValue, int newValue){
        try {
            // 通过反射获取Unsafe类中的theUnsafe对象
            Field theUnsafe = Unsafe.class.getDeclaredField("theUnsafe");
            theUnsafe.setAccessible(true); // 设置为可见
            Unsafe unsafe = (Unsafe) theUnsafe.get(null); // 获取Unsafe对象
            // 获取number的偏移量
            long offset = unsafe.objectFieldOffset(CasDemo.class.getDeclaredField("number"));
            // cas操作
            return unsafe.compareAndSwapInt(this, offset, oldValue, newValue);
        } catch (NoSuchFieldException e) {
            e.printStackTrace();
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        }
        return false;
    }

}
